home *** CD-ROM | disk | FTP | other *** search
- Unit CD_Unit;
-
- Interface
-
- Uses DOS, CD_Vars;
-
- Var
- Drive : Integer; { Must set drive before all operations }
- SubUnit : Integer;
-
- function File_Name(var Code : Integer) : String;
-
- function Read_VTOC(var VTOC : VTOCArray;
- var Index : Integer) : Boolean;
-
- procedure CD_Check(var Code : Integer);
-
- procedure Vol_Desc(Var Code : Integer;
- var ErrCode : Integer);
-
- procedure CD_Dev_Req(DevPointer : Pointer);
-
- procedure Get_Dir_Entry(PathName : String;
- var Format, ErrCode : Integer);
-
- procedure DeviceStatus;
-
- procedure Audio_Channel_Info;
-
- procedure Audio_Disk_Info;
-
- procedure Audio_Track_Info(Var StartPoint : LongInt;
- Var TrackControl : Byte);
-
- procedure Audio_Status_Info;
-
- procedure Q_Channel_Info;
-
- procedure Lock(LockDrive : Boolean);
-
- procedure Reset;
-
- procedure Eject;
-
- procedure CloseTray;
-
- procedure Resume_Play;
-
- procedure Pause_Audio;
-
- procedure Play_Audio(StartSec, EndSec : LongInt);
-
- function Sector_Size(ReadMode : Integer) : Word;
-
- function Volume_Size : LongInt;
-
- function Media_Changed : Boolean;
-
- function Head_Location(AddrMode : Byte) : LongInt;
-
- procedure Read_Drive_Bytes(Var ReadBytes : DriveByteArray);
-
- procedure Read_Long(TransAddr : Pointer; StartSec : Longint);
-
- procedure SeekSec(StartSec : Longint);
-
- procedure DevClose;
-
- procedure DevOpen;
-
- procedure OutputFlush;
-
- procedure InputFlush;
-
- function UPC_Code : String;
-
- Implementation
-
- Const
- CarryFlag = $0001;
-
- Type
- PointerHalf = Record
- LoHalf, HiHalf : Word;
- End;
-
- Var
- Regs : Registers;
- IOBlock : IOControl;
- DriveBytes : Array[1..130] of Byte;
-
- procedure Clear_Regs;
- begin
- FillChar(Regs, SizeOf(Regs), #0);
- end;
-
- procedure CD_Intr;
- begin
- Regs.AH := $15;
- Intr($2F, Regs);
- end;
-
- procedure MSCDEX_Ver;
- begin
- Clear_Regs;
- Regs.AL := $0C;
- Regs.BX := $0000;
- CD_Intr;
- MSCDEX_Version.Minor := 0;
- If Regs.BX = 0 Then
- MSCDEX_Version.Major := 1
- ELSE
- Begin
- MSCDEX_Version.Major := Regs.BH;
- MSCDEX_Version.Minor := Regs.BL;
- End;
- end;
-
- procedure Initialize;
- begin
- NumberOfCD := 0;
- Clear_Regs;
- Regs.AL := $00;
- Regs.BX := $0000;
- CD_Intr;
- If Regs.BX <> 0 THEN
- Begin
- NumberOfCD := Regs.BX;
- FirstCD := Regs.CX;
- Clear_Regs;
- FillChar(DriverList, SizeOf(DriverList), #0);
- FillChar(UnitList, SizeOf(UnitList), #0);
- Regs.AL := $01; { Get List of Driver Header Addresses }
- Regs.ES := Seg(DriverList);
- Regs.BX := Ofs(DriverList);
- CD_Intr;
- Clear_Regs;
- Regs.AL := $0D; { Get List of CD-ROM Units }
- Regs.ES := Seg(UnitList);
- Regs.BX := Ofs(UnitList);
- CD_Intr;
- MSCDEX_Ver;
- End;
- end;
-
-
- function File_Name(var Code : Integer) : String;
- Var
- FN : String[38];
- begin
- Clear_Regs;
- Regs.AL := Code + 1;
- {
- Copyright Filename = 1
- Abstract Filename = 2
- Bibliographic Filename = 3
- }
- Regs.CX := Drive;
- Regs.ES := Seg(FN);
- Regs.BX := Ofs(FN);
- CD_Intr;
- Code := Regs.AX;
- If (Regs.Flags AND CarryFlag) = 0 THEN
- File_Name := FN
- ELSE
- File_Name := '';
- end;
-
-
- function Read_VTOC(var VTOC : VTOCArray;
- var Index : Integer) : Boolean;
- { On entry -
- Index = Vol Desc Number to read from 0 to ?
- On return
- Case Index of
- 1 : Standard Volume Descriptor
- $FF : Volume Descriptor Terminator
- 0 : All others
- }
- begin
- Clear_Regs;
- Regs.AL := $05;
- Regs.CX := Drive;
- Regs.DX := Index;
- Regs.ES := Seg(VTOC);
- Regs.BX := Ofs(VTOC);
- CD_Intr;
- Index := Regs.AX;
- If (Regs.Flags AND CarryFlag) = 0 THEN
- Read_VTOC := TRUE
- ELSE
- Read_VTOC := FALSE;
- end;
-
- procedure CD_Check(var Code : Integer);
- begin
- Clear_Regs;
- Regs.AL := $0B;
- Regs.BX := $0000;
- Regs.CX := Drive;
- CD_Intr;
- If Regs.BX <> $ADAD THEN
- Code := 2
- ELSE
- Begin
- If Regs.AX <> 0 THEN
- Code := 0
- ELSE
- Code := 1;
- End;
- end;
-
-
- procedure Vol_Desc(Var Code : Integer;
- var ErrCode : Integer);
-
- function Get_Vol_Desc : Byte;
- begin
- Clear_Regs;
- Regs.CX := Drive;
- Regs.AL := $0E;
- Regs.BX := $0000;
- CD_Intr;
- Code := Regs.AX;
- If (Regs.Flags AND CarryFlag) <> 0 THEN
- ErrCode := $FF;
- Get_Vol_Desc := Regs.DH;
- end;
-
- begin
- Clear_Regs;
- ErrCode := 0;
- If Code <> 0 THEN
- Begin
- Regs.DH := Code;
- Regs.DL := 0;
- Regs.BX := $0001;
- Regs.AL := $0E;
- Regs.CX := Drive;
- CD_Intr;
- Code := Regs.AX;
- If (Regs.Flags AND CarryFlag) <> 0 THEN
- ErrCode := $FF;
- End;
- If ErrCode = 0 THEN
- Code := Get_Vol_Desc;
- end;
-
- procedure Get_Dir_Entry(PathName : String;
- var Format, ErrCode : Integer);
- begin
- FillChar(DirBuf, SizeOf(DirBuf), #0);
- PathName := PathName + #0;
- Clear_Regs;
- Regs.AL := $0F;
- Regs.CL := Drive;
- Regs.CH := 1;
- Regs.ES := Seg(PathName);
- Regs.BX := Ofs(PathName);
- Regs.SI := Seg(DirBuf);
- Regs.DI := Ofs(DirBuf);
- CD_Intr;
- ErrCode := Regs.AX;
- If (Regs.Flags AND CarryFlag) = 0 THEN
- Begin
- Move(DirBuf.NameArray[1], DirBuf.FileName[1], 38);
- DirBuf.FileName[0] := #12; { File names are only 8.3 }
- Format := Regs.AX
- End
- ELSE
- Format := $FF;
- end;
-
- procedure CD_Dev_Req(DevPointer : Pointer);
- begin
- Clear_Regs;
- Regs.AL := $10;
- Regs.CX := Drive;
- Regs.ES := PointerHalf(DevPointer).HiHalf;
- Regs.BX := PointerHalf(DevPointer).LoHalf;
- CD_Intr;
- end;
-
- procedure IO_Control(Command : Byte);
- begin
- IOBlock.IOReq_Hdr.Len := 26;
- IOBlock.IOReq_Hdr.SubUnit := SubUnit;
- IOBlock.IOReq_Hdr.Status := 0;
- IOBlock.TransAddr := @DriveBytes;
- IOBlock.IOReq_Hdr.Command := Command;
-
- FillChar(IOBlock.IOReq_Hdr.Reserved, 8, #0);
-
- CD_Dev_Req(@IOBlock);
-
- Busy := (IOBlock.IOReq_Hdr.Status AND 512) <> 0;
-
-
- end;
-
- procedure Audio_Channel_Info;
- begin
- FillChar(DriveBytes, SizeOf(DriveBytes), #0);
- DriveBytes[1] := 4;
- IOBlock.NumBytes := 9;
-
- IO_Control(IOCtlInput);
-
- Move(DriveBytes, AudioChannel, 9);
- End;
-
- procedure DeviceStatus;
- begin
- FillChar(DriveBytes, SizeOf(DriveBytes), #0);
-
- DriveBytes[1] := 6;
- IOBlock.NumBytes := 5;
-
- IO_Control(IOCtlInput);
- DoorOpen := DriveBytes[2] AND 1 <> 0;
- DoorLocked := DriveBytes[2] AND 2 <> 0;
- Audio := DriveBytes[2] AND 16 <> 0;
- AudioManip := DriveBytes[3] AND 1 <> 0;
- DiscInDrive := DriveBytes[3] AND 8 <> 0;
- RedBook := DriveBytes[3] AND 16 <> 0;
-
-
- End;
-
- procedure Audio_Disk_Info;
- begin
- FillChar(DriveBytes, SizeOf(DriveBytes), #0);
-
- DriveBytes[1] := 10;
- IOBlock.NumBytes := 7;
-
- IO_Control(IOCtlInput);
-
- Move(DriveBytes[2], AudioDiskInfo, 6);
-
- Playing := Busy;
-
- end;
-
- procedure Audio_Track_Info(Var StartPoint : LongInt;
- Var TrackControl : Byte);
- begin
- FillChar(DriveBytes, SizeOf(DriveBytes), #0);
-
- DriveBytes[1] := 11;
- DriveBytes[2] := TrackControl; { Track number }
- IOBlock.NumBytes := 7;
-
- IO_Control(IOCtlInput);
-
- Move(DriveBytes[3], StartPoint, 4);
-
- TrackControl := DriveBytes[7];
-
- Playing := Busy;
- end;
-
- procedure Q_Channel_Info;
- begin
- FillChar(DriveBytes, SizeOf(DriveBytes), #0);
-
- DriveBytes[1] := 12;
- IOBlock.NumBytes := 11;
-
- IO_Control(IOCtlInput);
-
- Move(DriveBytes[2], QChannelInfo, 11);
-
- end;
-
- procedure Audio_Status_Info;
- begin
- FillChar(DriveBytes, SizeOf(DriveBytes), #0);
-
- DriveBytes[1] := 15;
- IOBlock.NumBytes := 11;
-
- IO_Control(IOCtlInput);
-
- Paused := (Word(DriveBytes[2]) AND 1) <> 0;
-
- Move(DriveBytes[4], Last_Start, 4);
- Move(DriveBytes[8], Last_End, 4);
-
- Playing := Busy;
- end;
-
- procedure Eject;
- begin
- FillChar(DriveBytes, SizeOf(DriveBytes), #0);
-
- DriveBytes[1] := 0;
- IOBlock.NumBytes := 1;
-
- IO_Control(IOCtlOutput);
- end;
-
- procedure Reset;
- begin
- FillChar(DriveBytes, SizeOf(DriveBytes), #0);
-
- DriveBytes[1] := 2;
- IOBlock.NumBytes := 1;
-
- IO_Control(IOCtlOutput);
- Busy := TRUE;
- end;
-
- procedure Lock(LockDrive : Boolean);
- begin
- FillChar(DriveBytes, SizeOf(DriveBytes), #0);
-
- DriveBytes[1] := 1;
- If LockDrive THEN
- DriveBytes[2] := 1
- ELSE
- DriveBytes[2] := 0;
- IOBlock.NumBytes := 2;
-
- IO_Control(IOCtlOutput);
- end;
-
- procedure CloseTray;
- begin
- FillChar(DriveBytes, SizeOf(DriveBytes), #0);
-
- DriveBytes[1] := 5;
- IOBlock.NumBytes := 1;
-
- IO_Control(IOCtlOutput);
- end;
-
- Var
- AudioPlay : Audio_Play;
-
-
- function Play(StartLoc, NumSec : LongInt) : Boolean;
- begin
- FillChar(AudioPlay, SizeOf(AudioPlay), #0);
- AudioPlay.APReq.Command := PlayCD;
- AudioPlay.APReq.Len := 22;
- AudioPlay.APReq.SubUnit := SubUnit;
- AudioPlay.Start := StartLoc;
- AudioPlay.NumSecs := NumSec;
- AudioPlay.AddrMode := 1;
-
- CD_Dev_Req(@AudioPlay);
- Play := ((AudioPlay.APReq.Status AND 32768) = 0);
-
- end;
-
- procedure Play_Audio(StartSec, EndSec : LongInt);
- Var
- SP,
- EP : LongInt;
- SArray : Array[1..4] Of Byte;
- EArray : Array[1..4] Of Byte;
- begin
- Move(StartSec, SArray[1], 4);
- Move(EndSec, EArray[1], 4);
- SP := SArray[3]; { Must use longint or get negative result }
- SP := (SP*75*60) + (SArray[2]*75) + SArray[1];
- EP := EArray[3];
- EP := (EP*75*60) + (EArray[2]*75) + EArray[1];
- EP := EP-SP;
-
- Playing := Play(StartSec, EP);
- Audio_Status_Info;
- end;
-
- procedure Pause_Audio;
- begin
- If Playing THEN
- Begin
- FillChar(AudioPlay, SizeOf(AudioPlay), #0);
- AudioPlay.APReq.Command := StopPlay;
- AudioPlay.APReq.Len := 13;
- AudioPlay.APReq.SubUnit := SubUnit;
- CD_Dev_Req(@AudioPlay);
- end;
- Audio_Status_Info;
- Playing := FALSE;
- end;
-
- procedure Resume_Play;
- begin
- FillChar(AudioPlay, SizeOf(AudioPlay), #0);
- AudioPlay.APReq.Command := ResumePlay;
- AudioPlay.APReq.Len := 13;
- AudioPlay.APReq.SubUnit := SubUnit;
- CD_Dev_Req(@AudioPlay);
- Audio_Status_Info;
- end;
-
- function Sector_Size(ReadMode : Integer) : Word;
- Var SecSize : Word;
- begin
- FillChar(DriveBytes, SizeOf(DriveBytes), #0);
-
- DriveBytes[1] := 7;
- DriveBytes[2] := ReadMode;
-
- IOBlock.NumBytes := 4;
-
- IO_Control(IOCtlInput);
-
- Move(DriveBytes[3], SecSize, 2);
- Sector_Size := SecSize;
- End;
-
- function Volume_Size : LongInt;
- Var VolSize : LongInt;
- begin
- FillChar(DriveBytes, SizeOf(DriveBytes), #0);
-
- DriveBytes[1] := 8;
-
- IOBlock.NumBytes := 5;
-
- IO_Control(IOCtlInput);
-
- Move(DriveBytes[2], VolSize, 4);
- Volume_Size := VolSize;
- End;
-
- function Media_Changed : Boolean;
- Var MedChng : Byte;
-
- { 1 : Media not changed
- 0 : Don't Know
- -1 : Media changed
- }
- begin
- FillChar(DriveBytes, SizeOf(DriveBytes), #0);
-
- DriveBytes[1] := 9;
-
- IOBlock.NumBytes := 2;
-
- IO_Control(IOCtlInput);
-
- Move(DriveBytes[2], MedChng, 4);
- Inc(MedChng);
- Case MedChng of
- 2 : Media_Changed := False;
- 1,0 : Media_Changed := True;
- End;
- End;
-
- function Head_Location(AddrMode : Byte) : LongInt;
- Var
- HeadLoc : Longint;
- begin
- FillChar(DriveBytes, SizeOf(DriveBytes), #0);
-
- DriveBytes[1] := 1;
- DriveBytes[2] := AddrMode;
-
- IOBlock.NumBytes := 6;
-
- IO_Control(IOCtlInput);
-
- Move(DriveBytes[3], HeadLoc, 4);
- Head_Location := HeadLoc;
- End;
-
- procedure Read_Drive_Bytes(Var ReadBytes : DriveByteArray);
- Begin
- FillChar(DriveBytes, SizeOf(DriveBytes), #0);
-
- DriveBytes[1] := 5;
-
- IOBlock.NumBytes := 130;
-
- IO_Control(IOCtlInput);
-
- Move(DriveBytes[3], ReadBytes, 128);
- End;
-
- function UPC_Code : String;
- Var
- I, J, K : Integer;
- TempStr : String;
- Begin
- FillChar(DriveBytes, SizeOf(DriveBytes), #0);
- TempStr := '';
- DriveBytes[1] := 14;
-
- IOBlock.NumBytes := 11;
-
- IO_Control(IOCtlInput);
-
- If ((IOBlock.IOReq_Hdr.Status AND 32768) = 0) THEN;
- For I := 3 to 9 DO
- Begin
- J := DriveBytes[I] AND $0F;
- K := DriveBytes[I] AND $F0;
- TempStr := TempStr + Chr(J + 48);
- TempStr := TempStr + Chr(K + 48);
- End;
- If Length(TempStr) > 13 THEN
- TempStr[0] := Chr(Ord(TempStr[0])-1);
- UPC_Code := TempStr;
- End;
-
-
-
- procedure Read_Long(TransAddr : Pointer; StartSec : Longint);
- Var
- RL : ReadControl;
- {
- ReadControl = Record
- IOReq_Hdr : Req_Hdr;
- AddrMode : Byte;
- TransAddr : Pointer;
- NumSecs : Word;
- StartSec : LongInt;
- ReadMode : Byte;
- IL_Size,
- IL_Skip : Byte;
- End;
- }
- begin
- FillChar(RL, SizeOf(RL), #0);
- RL.IOReq_Hdr.Len := 27;
- RL.IOReq_Hdr.SubUnit := SubUnit;
- RL.IOReq_Hdr.Command := ReadLong;
- RL.AddrMode := 1;
- RL.TransAddr := TransAddr;
- RL.NumSecs := 1;
- RL.StartSec := StartSec;
- RL.ReadMode := 0;
- CD_Dev_Req(@RL);
- end;
-
- procedure SeekSec(StartSec : Longint);
- Var
- RL : ReadControl;
-
- begin
- FillChar(RL, SizeOf(RL), #0);
- RL.IOReq_Hdr.Len := 24;
- RL.IOReq_Hdr.SubUnit := SubUnit;
- RL.IOReq_Hdr.Command := SeekCmd;
- RL.AddrMode := 1;
- RL.StartSec := StartSec;
- RL.ReadMode := 0;
- CD_Dev_Req(@RL);
- end;
-
- procedure InputFlush;
- Var
- IOReq : Req_Hdr;
- begin
- FillChar(IOReq, SizeOf(IOReq), #0);
- With IOReq DO
- Begin
- Len := 13;
- SubUnit := SubUnit;
- Command := 7;
- Status := 0;
- end;
- CD_Dev_Req(@IOReq);
- end;
-
- procedure OutputFlush;
- Var
- IOReq : Req_Hdr;
- begin
- FillChar(IOReq, SizeOf(IOReq), #0);
- With IOReq DO
- Begin
- Len := 13;
- SubUnit := SubUnit;
- Command := 11;
- Status := 0;
- end;
- CD_Dev_Req(@IOReq);
- end;
-
- procedure DevOpen;
- Var
- IOReq : Req_Hdr;
- begin
- FillChar(IOReq, SizeOf(IOReq), #0);
- With IOReq DO
- Begin
- Len := 13;
- SubUnit := SubUnit;
- Command := 13;
- Status := 0;
- end;
- CD_Dev_Req(@IOReq);
- end;
-
- procedure DevClose;
- Var
- IOReq : Req_Hdr;
- begin
- FillChar(IOReq, SizeOf(IOReq), #0);
- With IOReq DO
- Begin
- Len := 13;
- SubUnit := SubUnit;
- Command := 14;
- Status := 0;
- end;
- CD_Dev_Req(@IOReq);
- end;
-
- {************************************************************}
-
- Begin
- NumberOfCD := 0;
- FirstCD := 0;
- FillChar(MSCDEX_Version, SizeOf(MSCDEX_Version), #0);
- Initialize;
- Drive := FirstCD;
- SubUnit := 0;
- End.
-